# coding=utf-8
from ..ToolsConfig import *
from BlueFoxSystem import BlueFoxServerSystem
from ..OtherTools import Mount
from LocalCoord import FixPosition, OriginCoord, RotCoord, RotAxes, BlockFaceRot

blockBlocks = {}
blockEntityDataComp = serverCompFactory.CreateBlockEntityData(LevelId)


def GetLoadedBlockBlockByPosDim(posDim):
    # type:(Tuple[int,int,int,int]) -> BlockBlock
    """
    通过维度坐标获取已经加载的方块块
    """
    return blockBlocks.get(posDim)


def GetLoadedBlockBlock():
    # type:() -> List[BlockBlock]
    """
    获取所有已加载的方块块
    """
    return list(set(blockBlocks.values()))


@Mount(BlueFoxServerSystem)
class BlockBlock(object):
    """
    方块块,用于解决模型体积过大导致的模型消失的问题
    """
    blueFoxSystem = BlueFoxServerSystem if 0 else None
    blockList = {}

    @classmethod
    def Load(cls, posDim):
        # type:(Tuple[int,int,int,int]) -> None
        """
        通过维度坐标加载储存的块数据
        """
        data = blockEntityDataComp.GetBlockEntityData(posDim[3], posDim[:3])
        if data and data['isCenter']:
            posDims = [tuple(_) for _ in data['posDims']]
            return cls(tuple(data['centerPosDim']), data['aux'], posDims)

    def __init__(self, posDim, aux, posDims=None):
        # type:(Tuple[int,int,int,int],int,List[Tuple]) -> None
        self.blockPosDims = posDims  # 方块块控制坐标
        self.centerPosDim = posDim  # 控制中心
        self.aux = aux

        if self.blockPosDims is None:
            self.blockPosDims = self.CreatePosDims(posDim, aux)
            self.CreateBlocks()
        self.dataComp = blockEntityDataComp.GetBlockEntityData(self.centerPosDim[3], self.centerPosDim[:3])
        self.dataComp['posDims'] = self.blockPosDims
        self.dataComp['aux'] = self.aux

        for posDim in self.blockPosDims:
            blockBlocks[posDim] = self

    def ReplaceBlocks(self, newBlockList, otherData):
        """
        替换方块，新方块依然具有方块实体的要求
        """
        oldData = {
            'posDims': self.blockPosDims,
            'aux': self.aux
        }
        oldData.update(otherData)
        self.DestroyBlocks()
        self.CreateBlocks(newBlockList)
        self.ResetBlockData(oldData)

    def ResetBlockData(self, data):
        for K_V in data.items():
            self.dataComp[K_V[0]] = K_V[1]

    def DestroyFunction(self):
        """
        销毁处理逻辑不清除方块
        """
        for posDim in self.blockPosDims:
            del blockBlocks[posDim]

    def Destroy(self):
        """
        销毁方块块
        """
        self.DestroyFunction()
        self.DestroyBlocks()

    def DestroyBlocks(self):
        """
        销毁方块块所控制的方块
        """
        blockComp = serverCompFactory.CreateBlockInfo(LevelId)
        for posDim in self.blockPosDims:
            blockComp.SetBlockNew(posDim[:3], blockDict={'name': 'minecraft:air'}, dimensionId=posDim[3])

    def CreateBlocks(self, blockList=None):
        """
        放置方块块所控制的方块
        """
        if blockList is None:
            blockList = self.blockList
        blockComp = serverCompFactory.CreateBlockInfo(LevelId)
        for pos in self.blockList:
            blockInfo = blockList[pos]
            blockInfo['aux'] = self.aux
            posDim = self.CalculatePosDimFromOffset(pos, self.centerPosDim, self.aux)
            blockComp.SetBlockNew(posDim[:3], blockDict=blockInfo, dimensionId=posDim[3])
            dataComp = blockEntityDataComp.GetBlockEntityData(posDim[3], posDim[:3])
            dataComp['isCenter'] = True if not cmp(pos, (0, 0, 0)) else False
            dataComp['centerPosDim'] = self.centerPosDim
        self.dataComp = serverCompFactory.CreateBlockEntityData(LevelId).GetBlockEntityData(
            self.centerPosDim[3], self.centerPosDim[:3]
        )

    def IsSelf(self, posDim):
        """
        判断一个维度坐标是否为本方块块
        """
        for posDimSelf in self.blockPosDims:
            if not cmp(posDimSelf, posDim):
                return True
        return False

    @classmethod
    def CreatePosDims(cls, posDim, aux):
        """
        创建方块块控制坐标
        """
        return [cls.CalculatePosDimFromOffset(pos, posDim, aux) for pos in cls.blockList]

    @classmethod
    def CalculatePosDimFromOffset(cls, offset, posDim, aux):
        originCoord = OriginCoord(posDim)
        _, __, ___ = FixPosition(originCoord.AbsPos(
            RotCoord(BlockFaceRot[aux], RotAxes.Y).CalculatePos(offset)
        ))
        return _, __, ___, posDim[3]

    @classmethod
    def Able(cls, posDim, aux):
        """
        判断是否可以生成块
        """
        blockComp = serverCompFactory.CreateBlockInfo(LevelId)
        for posDim in cls.CreatePosDims(posDim, aux):
            block = blockComp.GetBlockNew(posDim[:3], posDim[3])
            if block is None or (block and block['name'] != 'minecraft:air'):
                return False
        return True
